/* 
 * File:   Loader.cpp
 * Author: Lukas Gemela
 * 
 * Created on 11. listopad 2012, 8:44
 */

#include "Loader.h"
#include "StringUtils.h"

using namespace std;

Loader::Loader(string filename) :
		filename(filename), BG(BG_VALUE), IG(IG_VALUE), DELIMITIER(DELITIMIER_VALUE) {
}


Loader::~Loader() {
}

/**
 * načte vstupní soubor - vrací true pokud byl
 * soubor úspěšně načten.
 */
bool Loader::load() {
	vector<string> rows;
	if (!loadFileToVector(rows)) {
		cout << "File not found" << endl;
		return false;
	}
	parseLines(rows);
	return true;
}

/**
 * překlopí CVS soubor do objektů IFastDataApprox
 */
DataSet Loader::transformToDataSet(vector<string> &rows, int BGIndex,
		int IGIndex) {
	vector<string> row;
	p_BGValues.reset();
	p_IGValues.reset();
	p_BGValues = make_shared<DataSet>();
	p_IGValues = make_shared<DataSet>();
	DataSet data;
	for (unsigned i = 0; i < rows.size(); i++) {
		csvline_populate(row, rows[i], DELIMITIER);
		StringUtils::replace(row[BGIndex], ",", ".");
		StringUtils::replace(row[IGIndex], ",", ".");
		p_BGValues->add(StringUtils::convertToDouble(row[BGIndex]));
		p_IGValues->add(StringUtils::convertToDouble(row[IGIndex]));
	}
	return data;
}

/**
 * Zparsuje řádky CVS do vektorů. řádky, kde nejsou naměřeny obě hodnoty,
 * jsou přeskočeny.
 */
DataSet Loader::parseLines(std::vector<string> &rows) {
	std::vector<string> row;
	string line = rows[0];
	csvline_populate(row, line, DELIMITIER);
	int BGIndex = -1;
	int IGIndex = -1;
	findColumnsIndex(row, &BGIndex, &IGIndex);

	//remove header

	rows.erase(rows.begin());

	std::vector<std::string>::iterator iter = rows.begin();
	while (iter != rows.end())
	{
		std::vector<string> actRow;
		csvline_populate(actRow, iter->c_str(), DELIMITIER);
	    if(actRow[BGIndex].empty() || actRow[IGIndex].empty())
	    {
	        // erase returns the new iterator
	        iter = rows.erase(iter);
	    }
	    else
	    {
	        ++iter;
	    }
	}
	return transformToDataSet(rows, BGIndex, IGIndex);

}

/**
 * Načte soubor do vektoru jednotlivých řádek.
 */
bool Loader::loadFileToVector(vector<string> &rows) {
	ifstream in(filename.c_str());
	string line;
	if (in.fail()) {
		in.close();
		return false;
	}

	while (getline(in, line) && in.good()) {
		rows.push_back(line);
	}
	in.close();

	return true;
}

/**
 * parsuje jeden řádek CVS do vektoru hodnot.
 */
void Loader::csvline_populate(vector<string> &record, const string& line,
		char delimiter) {
	int linepos = 0;
	int inquotes = false;
	char c;
	//    int i;
	int linemax = line.length();
	string curstring;
	record.clear();

	while (line[linepos] != 0 && linepos < linemax) {

		c = line[linepos];

		if (!inquotes && curstring.length() == 0 && c == '"') {
			//beginquotechar
			inquotes = true;
		} else if (inquotes && c == '"') {
			//quotechar
			if ((linepos + 1 < linemax) && (line[linepos + 1] == '"')) {
				//encountered 2 double quotes in a row (resolves to 1 double quote)
				curstring.push_back(c);
				linepos++;
			} else {
				//endquotechar
				inquotes = false;
			}
		} else if (!inquotes && c == delimiter) {
			//end of field
			record.push_back(curstring);
			curstring = "";
		} else if (!inquotes && (c == '\r' || c == '\n')) {
			record.push_back(curstring);
			return;
		} else {
			curstring.push_back(c);
		}
		linepos++;
	}
	record.push_back(curstring);
	return;
}

/**
 * vyhledá indexy hledaných veličin v headeru CVS.
 */
void Loader::findColumnsIndex(vector<string> header, int *BGIndex,
		int *IGIndex) {
	for (unsigned i = 0; i < header.size(); i++) {

		if (!header[i].compare(BG)) {
			*BGIndex = i;
		} else if (!header[i].compare(IG)) {
			*IGIndex = i;
		}
	}
}

